<?php 
    // 数据库操作
    /*
    1.数据库配置项,写到config.php里
    'DB_TYPE'=>'mysql',
    'DB_HOST'=>'127.0.0.1',#如果要主从分离写多个服务器地址,用,隔开
    'DB_NAME'=>'test',
    'DB_USER'=>'root',
    'DB_PWD'=>'',
    'DB_PORT'=>'3306',
    'DB_PREFIX'=>'',#表前缀
    // 开启主从读写分离
    'DB_RW_SEPARATE'=>true,
    // 多个主数据库服务器
    'DB_MASTER_NUM'=>2,   
    2.命名空间的注意事项
        1)Controller文件中命名空间的使用
        namespace Home\Controller;
        use Think\Controller;
        use Home\Model\UserModel;#也可以在实例化的时候单独写,比如 new \Home\Model\UserModel
        class IndexController extends Controller{}

        2)Model文件中命名空间的使用
        namespace Home\Model;
        use Think\Model;
        class UserModel extends Model{}

        3)关于公共模型的使用.由于模型文件经常需要用到同样功能的方法,所以将这些方法都写到一个ComonModel
        文件里,其他的Model文件都继承这个CommonModel文件就可以调用了,而且也省去了use Think\Model这一步.
        具体写法:
        //CommonModel.class.php下
        namespace Home\Model;
        use Think\Model;
        class CommonModel extends Model{}
        //其他模型文件,例如UserModel.class.php下
        namespace Home\Model;
        class UserModel extends CommonModel{}
    3.在Thinkphp中的实例化方法
        1)M函数
        M('表名')  基于基础模型实例化.
        2)D函数
        D('模型名') 基于用户自定义模型实例化.需要建立对应的'模型名Model.class.php'文件.模型名严格区分大小写.
        注意:如果对应的模型文件不存在时,本函数会自动转换为M函数来使用.
        3)空模型,用于需要写原生语句的情况下,相比前两者自由度更高
        $model=M();
        $model->query($sql);#仅能用于查询
        $model->execute($sql);#仅能用于写入操作:增删改
    4.CURD
        1)C 增加数据
        //单条数据增加,可以返回自增ID
        M('模型名')->add(['字段名'=>'字段值','字段名'=>'字段值'])
        //多条数据增加,只能返回第一条数据的自增ID,且仅能用于mysql数据库
        $array=[
            0=>['字段名'=>'字段值','字段名'=>'字段值'],
            1=>['字段名'=>'字段值','字段名'=>'字段值'],
            2=>['字段名'=>'字段值','字段名'=>'字段值']
        ];
        M('模型名')->addAll($array);
        //获取原生查询语句,注意没有模型名.当然如果开启了页面调试,也可以直接在SQL一项中看到
        M()->getLastSql();

        2)R 查询数据
        // 单一条件查询
        $res=M('user')->where('uid>13')->select();

        // 多条件查询.定义一个数组变量$where,以$where['字段名']的形式赋对应的查询值.$where['_logic']可以改变
        // 逻辑,默认是and,可以写为or
        $where=[];
        $where['_logic']='or';
        $where['uid']=17;
        $where['username']='马三立';
        $res=M('user')->where($where)->select();

        // 表达式查询.定义一个数组变量$where,以$where['字段名']=['逻辑',比对值]的形式赋值.多条件用数组形式分离
        $where=[];
        $where['uid']=['gt',15];
        $where['uid']=['between','15,20'];
        $where['uid']=['in','13,17,19'];
        $where['uid']=[['lt',20],['gt',15]];
        $res=M('user')->where($where)->select();

        // 模糊查询.写法与表达式查询一致.多条件模糊查询只需要把模糊条件数组化即可
        $where=[];
        $where['username']=['like','%三%'];#单条件
        $where['username']=['like',['%三%','%一%']];#多条件
        $res=M('user')->where($where)->select();

        // 区间查询,默认是and,可修改为or执行,比如大于10小于5的情况,必须改为or
        $where=[];
        $where['uid']=[['gt',20],['lt',16],'or'];
        $res=M('user')->where($where)->select();

        // 混合用法,指的是条件后跟自定义字符串查询的方式,字符串语句定义在$where['_string']中.本方法不推荐使用,因为如果
        // 字符串中插入;或''等符号可以造成语句错误甚至注入
        $where=[];
        $where['uid']=['gt',15];
        $where['_string']='username like "%三%"';
        $res=M('user')->where($where)->select();

        // 统计类用法,count/max/min/avg/sum
        $res=M('user')->count();#可以不传值.其他几个必须传入一个具体的字段名
        $res=M('user')->max('uid');
        $res=M('user')->avg('uid');
        $res=M('user')->sum('uid');

        3)U 更新数据,写法和查询基本一致.其他区间/比较 等写法均可参考查询的写法.自行尝试
        $update=[];
        $update['username']='马三座';
        $update['age']=88;
        $where=[];
        $where['uid']=15;
        $data=M('user')->where($where)->save($update);
        4)D 删除数据,写法和查询基本一致
        $where=[];
        $where['uid']=16;
        $data=M('user')->where($where)->delete();
        // 或者用传入主键的方法,可以传入字符串'1,2,3'的形式连续删除
        $data=M('user')->delete(20);

    5.连贯操作.各项操作可以不分次序的连接使用.比如M('user')->order('age desc')->field('age,username',false)->select();
        1)order排序,多条件用,分隔,参数整体是字符串形式
        $res=M('user')->order('age desc,uid asc')->select();

        2)field筛选.field('筛选字段1,筛选字段2,....',反向筛选true/正向筛选false(默认值,可不写))
        $res=M('user')->field('username,age',true)->select();
        结果:
        Array
        (
            [0] => Array
                (
                    [uid] => 11
                )
        )   

        $res=M('user')->field('username,age',false)->select();
        结果:
        Array
        (
            [0] => Array
                (
                    [username] => '马三立',
                    [age]=>25
                )
        )
        
        3)limit(起始数,条数)
        $res=M('user')->limit(0,6)->select();
        
        4)page(当前页,每页的条数).不推荐使用此方法分页,因为功能过于简单.请学习使用thinkphp单独的分页类
        $res=M('user')->page(1,5)->select();     

        5)group和having
        $res=M('user')->having('age>30')->group('age')->select();
        //mysql知识点补充
        group by 分组 
        having 是对分组后的结果 做条件查询
        where 是查询条件完成后在分组，一个在前一个在后 

    6.多表查询
        1)table(['表名'=>'别名','表名'=>'别名'])  此方法表名需要加前缀.也不推荐使用
        $res=M()->table(['mk_user'=>'user','mk_userinfo'=>'info'])->where('user.id=info.user_id')->select();
        
        2)join 分为字符串和数组两种形式
        // 字符串方式查询
        $res=M('user')->join('userinfo on uid=user_uid')->select();
        // 字符串多关联查询
        $res=M('user')->join('userinfo on uid=user_uid')->join('条件')->join('条件')->select();
        // 左右关联,写到join条件的开头
        $res=M('user')->join('left/right join userinfo on uid=user_uid')->select();
        // 数组方式查询,用于2个或2个以上的表关联查询时相比字符串形式更简洁
        $res=M('user')->join(['userinfo on uid=user_uid','moneylevel on money=user_money'])->select();

        3)union(string/array,false(默认值,可不写.union查询)/true(union all 查询))
            1)union all是不过滤重复的,union是过滤重复的
            2)对于条件,多字段用,分隔且顺序必须前后一致,无论是字符串形式还是数组形式
        // 字符串形式
        $res=M('user')->field('username,uid')->union('select username,uid from user')->select();
        // 数组形式
        $res=M('user')->field('username')->union(['field'=>'username','table'=>'user'])->select();
        // 数组形式多条查询
        $res=M('user')
        ->field('username')
        ->union(['field'=>'username','table'=>'user'])
        ->union(['field'=>'username','table'=>'user2'])
        ->select();

        4)distinct 过滤查询
        $res=M('user')->distinct(true)->field('age')->order('age asc')->select();

        所有的关联查询,都要基于性能考虑,如果有索引则尽量使用索引

    7.命名范围的使用,可以封装一些查询操作到模型中.以下内容写到对应的模型文件中
    namespace Home\Model;
    class UserModel extends CommonModel
    {
        protected $_scope=[
            '命名范围掐标识名'=>[
                '属性'=>'值',
                支持的方法有 where limit field order table page having group distinct
            ],
            'rich'=>[
                'where'=>[
                    'uid'=>[
                        'egt',17
                    ],
                ],
                'order'=>'uid asc',
            ],
            'ziduan'=>[
                'field'=>'username,age',
            ],
        ];
    }
     */

 ?>